package com.pingpang.common.code.impl;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import com.pingpang.common.code.MessageCodecUtil;

public class ProtostuffCodeUtil implements MessageCodecUtil{
	  private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<Class<?>, Schema<?>>();

	    private static <T> Schema<T> getSchema(Class<T> clazz) {
	        @SuppressWarnings("unchecked")
	        Schema<T> schema = (Schema<T>) cachedSchema.get(clazz);
	        if (schema == null) {
	            schema = RuntimeSchema.getSchema(clazz);
	            if (schema != null) {
	                cachedSchema.put(clazz, schema);
	            }
	        }
	        return schema;
	    }
	    
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public byte[] encode(Object obj) throws IOException {
		Class clazz =  obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
			Schema schema = getSchema(clazz);
            return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
	}

	@Override
	public Object decode(byte[] body, Class cls) throws IOException {
		try {
            Object obj = cls.newInstance();
            Schema schema = getSchema(cls);
            ProtostuffIOUtil.mergeFrom(body, obj, schema);
            return obj;
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
	}

}
